Fall back to fs::copy when hard_link fails.
authorCliff L. Biffle <code@cliffle.com>
Sun, 25 Sep 2016 20:53:07 +0000 (13:53 -0700)
committerCliff L. Biffle <code@cliffle.com>
Sun, 25 Sep 2016 20:57:26 +0000 (13:57 -0700)
Some filesystems don't allow hard links.  Since Cargo's use of hard
links is an optimization, and not necessary for correctness, it can fall
back to a file copy when hard linking is not available.

This is one possible solution to #3098.

Caveat: this will try to copy if the hard link fails *for any reason*.
It's not clear that there's a more surgical way of handling this; Unix
tends to indicate the condition as "permission denied," not with a
granular "links not supported by filesystem" error.

src/cargo/ops/cargo_rustc/mod.rs

index b36ed3cebd14ab52a784a96215de750e81013013..59d1ec57f632267b47826bb3ead91f83a32815b7 100644 (file)
@@ -317,9 +317,11 @@ fn rustc(cx: &mut Context, unit: &Unit) -> CargoResult<Work> {
                         human(format!("failed to remove: {}", dst.display()))
                     }));
                 }
-                try!(fs::hard_link(&src, &dst).chain_error(|| {
-                    human(format!("failed to link `{}` to `{}`",
-                                  src.display(), dst.display()))
+                try!(fs::hard_link(&src, &dst)
+                     .or_else(|_| fs::copy(&src, &dst).map(|_| ()))
+                     .chain_error(|| {
+                         human(format!("failed to link or copy `{}` to `{}`",
+                                       src.display(), dst.display()))
                 }));
             }
         }